package hehe.aop.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * aop 注解
 *<B>说明：</B>
 *<pre>
 * 略
 *</pre>
 *<B>示例：</B>
 *<pre>
 *  略
 *</pre>
 *<B>日志：</B>
 *<pre>
 *  略
 *</pre>
 *<B>注意事项：</B>
 *<pre>
 *  略
 *</pre>
 */
public class AopAnnotation
{
    protected final static String METHOD_ANNOTATION_NAME = "method";
    protected final static String CLAZZ_ANNOTATION_NAME = "clazz";

    /**
     * 支持注解列表
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected static List<Class> annotationList = new ArrayList<Class>(){{
        add(Before.class);
        add(After.class);
        add(Throw.class);
        add(Finally.class);
        add(Around.class);
        add(Aspect.class);
    }};

    /**
     * 注解解析缓存
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected static Map<Class,Boolean> parseAnnotationCache = new HashMap<>();

    /**
     * 解析注解
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public static void parseAnnotation(Class targetclazz) throws Exception
    {
        if (parseAnnotationCache.containsKey(targetclazz)) {
            return;
        }

        // 解析类注解
        parseClassAnnotation(targetclazz,annotationList);
        // 解析方法注解
        parseMethodAnnotation(targetclazz,annotationList);

        parseAnnotationCache.put(targetclazz,true);
    }

    /**
     * 解析类注解
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public static void parseClassAnnotation(Class targetclazz, List<Class> annotationList) throws Exception
    {
        Method processorMethod;
        Annotation[] annotations = targetclazz.getDeclaredAnnotations();
        if (annotations.length == 0) {
            return;
        }

        for (Annotation ann:annotations) {
            if (annotationList.contains(ann.annotationType())) {
                Class annotationProcessor = getAnnotationProcessor(ann);
                if (annotationProcessor != null) {
                    processorMethod = annotationProcessor.getMethod(CLAZZ_ANNOTATION_NAME, Class.class,Annotation.class);
                    processorMethod.invoke(annotationProcessor.newInstance(),targetclazz,ann);
                }
            }
        }
    }

    /**
     * 解析方法注解
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public static void parseMethodAnnotation(Class targetclazz, List<Class> annotationList) throws Exception
    {
        Method[] methods = targetclazz.getMethods();
        Annotation[] annotations;
        Method processorMethod;
        for (Method method:methods) {
            annotations = method.getDeclaredAnnotations();
            if (annotations.length == 0) {
                continue;
            }

            for (Annotation ann:annotations) {
                if (annotationList.contains(ann.annotationType())) {
                    Class annotationProcessor = getAnnotationProcessor(ann);
                    if (annotationProcessor != null) {
                        processorMethod = annotationProcessor.getMethod(METHOD_ANNOTATION_NAME, Class.class,Method.class,Annotation.class);
                        processorMethod.invoke(annotationProcessor.newInstance(),targetclazz,method,ann);
                    }
                }
            }
        }
    }


    /**
     * 获取注解的处理器
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public static Class<?> getAnnotationProcessor(Annotation annotation)
    {
        AopProcessor processor = annotation.annotationType().getAnnotation(AopProcessor.class);
        if (processor != null) {
            return processor.processor();
        }

        return null;
    }

}
